﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using JXT.PrimaryKey.Batman.Collections;
using JXT.PrimaryKey.Batman.Core.Language;
using JXT.PrimaryKey.Batman.Core.Extensions;
using JXT.PrimaryKey.Batman.Web.Mvc.Models;
using JXT.PrimaryKey.Batman.Core.Security;
using JXT.PrimaryKey.Batman.Web.Mvc.Filters;
using JXT.PrimaryKey.Batman.Web.Mvc.Extensions;
using JXT.PrimaryKey.Batman.Web.Mvc.Results;
using JXT.PrimaryKey.Batman.Domain.Specifications;
using JXT.PrimaryKey.Batman.Domain.UserSystem.Models;
using JXT.PrimaryKey.Batman.Domain.UserSystem.Services;

namespace JXT.PrimaryKey.Batman.Web.Mvc.Controllers
{
    public class AuthenticationController : BaseController
    {
        private static readonly string _cookieKey = "login_token";

        private static readonly string _tokenUrlParameter = "token";

        private static readonly string _errorUrlParameter = "error";

        private static readonly string _jsVariableName = "login_token";

        [HttpPost]
        [ActionName("login")]
        public ActionResult Login(ViewLoginUser user)
        {
            
            if (!ModelState.IsValid)
                return Message("登录网关错误", "错误的登录参数！", MessageIcon.Error);
            Uri uri;
            if (!Uri.TryCreate(user.ReturnUrl, UriKind.Absolute, out uri))
                return Message("验证网关错误", "错误的返回url参数！", MessageIcon.Error);
            if(String.IsNullOrWhiteSpace(user.Mail) && String.IsNullOrWhiteSpace(user.Name))
                return Message("登录网关错误", "必须存在登录凭证！", MessageIcon.Error);
            if (user.Expires == null)
                user.Expires = DateTime.Now.AddDays(1); //默认保存1天
            var loginStatus = LoadService<IUserService>().Login(user.Name, user.Mail, user.Password, WebEnvironment.UserIp, user.Expires);
            if (loginStatus == null)
                return Redirect(uri.AddUrlParameter(_errorUrlParameter, (byte)AuthenticationErrorCode.LoginAuthorizationError));
            var cookie = new HttpCookie(_cookieKey);
            cookie.Value = loginStatus.Token;
            if (user.Expires != null)
                cookie.Expires = user.Expires.Value;
            Response.AddP3PHeader();
            Response.Cookies.Add(cookie);
            return Redirect(uri.AddUrlParameter(_tokenUrlParameter, loginStatus.Token));
        }

        [HttpGet]
        [ActionName("check")]
        public ActionResult Check(string returnUrl)
        {
            Uri uri;
            if (!Uri.TryCreate(returnUrl, UriKind.Absolute, out uri))
                return Message("验证网关错误", "错误的返回url参数！", MessageIcon.Error);
            var cookie = Request.Cookies.Get(_cookieKey);
            if (cookie == null)
                return Redirect(uri.AddUrlParameter(_errorUrlParameter, (byte)AuthenticationErrorCode.CookieError));
            var user = LoadService<IUserService>().GetLoginSingle(cookie.Value);
            if (user == null)
            {
                Response.Cookies.Remove(_cookieKey);
                return Redirect(uri.AddUrlParameter(_errorUrlParameter, (byte)AuthenticationErrorCode.TokenFailure));
            }
            return Redirect(uri.AddUrlParameter(_tokenUrlParameter, user.loginStatus.Token));
        }

        [HttpGet]
        [ActionName("logout")]
        public ActionResult Logout(string returnUrl)
        {
            Uri uri;
            if (!Uri.TryCreate(returnUrl, UriKind.Absolute, out uri))
                return Message("验证网关错误", "错误的返回url参数！", MessageIcon.Error);
            var cookie = Request.Cookies.Get(_cookieKey);
            if (cookie == null)
                return Redirect(uri.AddUrlParameter(_errorUrlParameter, (byte)AuthenticationErrorCode.CookieError));
            try
            {
                LoadService<IUserService>().Logout(cookie.Value);
                Response.Cookies.Remove(_cookieKey);
                return Redirect(uri.ToString());
            }
            catch(Exception e)
            {
                LoadService<IAuthenticationLogService>().Add("user logout error!", e.Message);
                return Redirect(uri.AddUrlParameter(_errorUrlParameter, (byte)AuthenticationErrorCode.TokenFailure));
            }
        }

        [HttpGet]
        [ActionName("jsstatus")]
        public ActionResult JsStatus()
        {
            string jsFormat = "var {0} = \"{1}\";";
            string nullJs = String.Format("var {0} = null;", _jsVariableName);
            if (Request.Cookies[_cookieKey] == null)
                return JavaScript(nullJs);
            HttpCookie cookie = Request.Cookies[_cookieKey];
            string token = cookie.Value.Trim();
            User user = LoadService<IUserService>().GetLoginSingle(token);
            if (user == null)
            {
                Response.Cookies.Remove(_cookieKey);
                return JavaScript(nullJs);
            }
            
            return JavaScript(String.Format(jsFormat, _jsVariableName, user.loginStatus.Token));
        }

        [HttpGet]
        [ActionName("jsonstatus")]
        public ActionResult JsonStatus(string callback)
        {
            if (String.IsNullOrWhiteSpace(callback))
                return Json(new { IsSuccess = false }, JsonRequestBehavior.AllowGet);
            if (Request.Cookies[_cookieKey] == null)
                return Jsonp(callback, new { IsSuccess = false });
            HttpCookie cookie = Request.Cookies[_cookieKey];
            string token = cookie.Value.Trim();
            User user = LoadService<IUserService>().GetLoginSingle(token);
            if (user == null)
            {
                Response.Cookies.Remove(_cookieKey);
                return Jsonp(callback, new { IsSuccess = false });
            }
            return Jsonp(callback, new { IsSuccess = true, Status = user.loginStatus });
        }
    }
}
